
***Replication code for "Climate information on sea level rise risk influences individuals' migration preferences in Vietnam."
*Authors: Laura Bakkensen, Quynh Nguyen, Toan Phan, and Paul Schuler
*Version: August 5, 2025
*Statistical program: Stata Version 19.5
*Data file: migration.dta

*******************************************************************************
*** Paper Replication Results ***
*******************************************************************************

/* STEP 1 Replication code
*Step 1.1: Set survey weights
*Step 1.2: Table 1: Effects of Information Treatments
*Step 1.3: Figure 1: Marginal Effects Graph
*Step 1.4: Materials and Methods Statistic: Power Calculations
*Step 1.5: Figure A2: Marginal Effects Graph
*Step 1.6: Table A1: Summary statistics
*Step 1.7: Table A2: Control Balance Tests Across Treatments
*Step 1.8: Table A3: Main Results: Details
*Step 1.9: Table A4: Robustness: Alternative Definitions of Willingness to Migrate Variable and of At Risk Dummy
*Step 1.10: Table A5: Robustness: Additional Sensitivity
*Step 1.11: Table A6: Mechanisms
*/

use migration.dta, replace

***Step 1.1: Set survey weights ***
******************************************************************************
 
svyset PSW_PSU [pweight=PSW_psweight_opt4], fpc(PSW_FPC1) strata(PSW_STRATA) singleunit(certainty) ///
 || PSW_SSU, fpc(PSW_FPC2) strata(PSW_STRATA2) || villageid, fpc(PSW_FPC3) strata(PSW_STRATA3) ///
 || _n,  poststrata(tinh)  postweight(PSW_province_population)
 

***Step 1.2: Table 1: Effects of Information Treatments***
*******************************************************************************
est clear
eststo: svy: reg move4 1.info 1.map 1.neg if group < 6
test 1.info + 1.map + 1.neg ==0
eststo: svy: reg move4 (1.info 1.map 1.neg)##1.flooded if group < 6
test 1.info + 1.map + 1.neg  + 1.info#1.flooded + 1.map#1.flooded + 1.neg#1.flooded==0
eststo: svy:  reg move4 1.info 1.map 1.neg experience_flood family_outside c.stuff  c.education c.hh_member c.hh_member_18 c.risk_averse male c.age ethnicity hh_head if group < 6
test 1.info + 1.map + 1.neg ==0
*Jointly significant
eststo: svy: reg move4_01 (1.info 1.map 1.neg experience_flood family_outside c.stuff  c.education c.hh_member c.hh_member_18 c.risk_averse male c.age ethnicity hh_head)##1.flooded if group < 6
test 1.info + 1.map + 1.neg  + 1.info#1.flooded + 1.map#1.flooded + 1.neg#1.flooded==0
*Jointly significant

esttab using "Table_1.csv", replace b(3) se(3) star(* 0.10 ** 0.05 *** 0.01) stats(N r2_a) mtitles("move4>0"  "move4>0 flooded" "move4>0 flooded controls" "move4>0 flooded controls interaction") order(*info* *map* *flooded*)
*Note: for parsimony, the control variable coefficients are not presented in Table 1. Full results are presented in Table A2. 

***Step 1.3: Figure 1: Marginal Effects Graph ***
*******************************************************************************
mat estimates = J(11,8,999)
svy: reg move4_01 (i.info i.map i.neg experience_flood family_outside c.stuff  c.education c.hh_member c.hh_member_18 c.risk_averse male c.age ethnicity hh_head)##i.flooded if group < 6
margins info#flooded, at(map==0) post
mat estimates[3,1]=r(table)
svy: reg move4_01 (i.info i.map i.neg experience_flood family_outside c.stuff  c.education c.hh_member c.hh_member_18 c.risk_averse male c.age ethnicity hh_head)##i.flooded if group < 6
margins map#flooded, at(info==1) post
mat estimates[3,5]=r(table)
mat estimates2=estimates'
mat list estimates2
mat estimates2[1,1]=[.95,1.05,999,999,1.95,2.05,2.95,3.05]'
mat estimates2[1,2]=[1,2,1,2,1,2,1,2]'
mat list estimates2
svmat estimates2
label var estimates21 

label define estimates21 1 "No Information" 2 "Information " 3 "Information and Map" 
label values estimates21 estimates21
label define estimates22 1 "No Flood Risk" 2 "Flood Risk " 
label values estimates22 estimates22

format estimates23 %9.3f

twoway (scatter  estimates23 estimates21 if estimates21!=999, mlabel(estimates23) mlabcolor(black) mcolor(red)) (rcap estimates27 estimates28 estimates21 if estimates21!=999 & estimates22==1, lcolor(gray))  (rcap estimates27 estimates28 estimates21 if estimates21!=999 & estimates22==2, lcolor(red) lwidth(thick) xlabel( 1 "Control" 2 "Text" 3 "Text + Map"  ) xtitle("") legend(order( 2 "Less at SLR risk" 3 "At SLR risk") pos(6) row(1)) graphregion(margin(10 10 2 2)) ytitle("Likelihood of Migration")) 

graph save "Figure_1", replace

graph export Figure_1.png, as(png) replace

***Step 1.4: Materials and Methods Statistic: Power Calculations ***
*******************************************************************************
*Estimated sample size for multiple linear regression
*F test for R2 testing all coefficients
*https://www.stata.com/manuals/pss.pdf

*power rsquared 0.0361, ntested(29) n(7307)
*Power is close to 1.000
power rsquared 0.0361, ntested(29) power(.95)
*Minimum sample size is 959 for 95% power

*******************************************************************************
*********APPENDIX**************************************************************
*******************************************************************************

***Step 1.5: Figure A2: Marginal Effects Graph ***
*******************************************************************************
mat estimates3 = J(11,12,999)
svy: reg move4_01 (i.info i.map i.neg experience_flood family_outside c.stuff  c.education c.hh_member c.hh_member_18 c.risk_averse male c.age ethnicity hh_head)##i.flooded if group < 6
margins info#flooded, at(map==0 neg==0) post
mat estimates3[3,1]=r(table)
svy: reg move4_01 (i.info i.map i.neg experience_flood family_outside c.stuff  c.education c.hh_member c.hh_member_18 c.risk_averse male c.age ethnicity hh_head)##i.flooded if group < 6
margins neg#flooded, at(info==1 map==0) post
mat estimates3[3,5]=r(table)
svy: reg move4_01 (i.info i.map i.neg experience_flood family_outside c.stuff  c.education c.hh_member c.hh_member_18 c.risk_averse male c.age ethnicity hh_head)##i.flooded if group < 6
margins neg#flooded, at(info==1 map==1) post
mat estimates3[3,9]=r(table)

mat estimates4=estimates3'
mat list estimates4
mat estimates4[1,1]=[.95,1.05,999,999,1.95,2.05,2.95,3.05,3.95,4.05, 4.95,5.05]'
mat estimates4[1,2]=[1,2,1,2,1,2,1,2,1,2,1,2]'
mat list estimates4
svmat estimates4
label var estimates41 

label define estimates41 1 "No Information (no )" 2 "No Negative (no map)" 3 "Negative (no map)" 4 "No Negative (map)" 5 "Negative (map)"
label values estimates41 estimates41
label define estimates42 1 "No Flood Risk" 2 "Flood Risk " 
label values estimates42 estimates42

format estimates43 %9.3f

twoway (scatter  estimates43 estimates41 if estimates41!=999, mlabel(estimates43) mcolor(red) mlabcolor(black))  (rcap estimates47 estimates48 estimates41 if estimates41!=999 & estimates42==1, lcolor(gray))  (rcap estimates47 estimates48 estimates41 if estimates41!=999 & estimates42==2, lcolor(red) lwidth(thick) xlabel( 1 "Control" 2 "Text" 3 `""Text""+ Doubt""' 4 "Text + Map" 5 `""Text + Map""+ Doubt""', labsize(small)) xtitle("") legend(order( 2 "Less at SLR risk" 3 "At SLR risk") pos(6) row(1)) graphregion(margin(10 10 2 2)) ytitle("Likelihood of Migration")) 

graph save "Figure_A2", replace
graph export Figure_A2.png, as(png) replace


***Step 1.6: Table A1: Summary statistics ***
*******************************************************************************
est clear
estpost summarize move4x move4x01 info map flooded flooded50 PFlood2050 experience_flood family_outside stuff  education hh_member hh_member_18 risk_averse male age if group<6

esttab using "summary_stat.csv", replace cells("count mean sd min max")

***Step 1.7: Table A2: Control Balance Tests Across Treatments***
*******************************************************************************
*Information Treatment
ttest family_outside if group<6, by(info) 
ttest stuff if group<6, by(info)
ttest education if group<6, by(info)
ttest hh_member if group<6, by(info)
ttest hh_member_18 if group<6, by(info)
ttest risk_averse if group<6, by(info)
ttest male if group<6, by(info)
ttest age if group<6, by(info)
ttest ethnicity if group<6, by(info)
ttest hh_head if group<6, by(info)
ttest experience_flood if group<6, by(info)
ttest flooded if group<6, by(info)

*Map Treatment
ttest family_outside if group<6, by(map) 
ttest stuff if group<6, by(map)
ttest education if group<6, by(map)
ttest hh_member if group<6, by(map)
ttest hh_member_18 if group<6, by(map)
ttest risk_averse if group<6, by(map)
ttest male if group<6, by(map)
ttest age if group<6, by(map)
ttest ethnicity if group<6, by(map)
ttest hh_head if group<6, by(map)
ttest experience_flood if group<6, by(map)
ttest flooded if group<6, by(map)

*Doubt Treatment
ttest family_outside if group<6, by(neg) 
ttest stuff if group<6, by(neg)
ttest education if group<6, by(neg)
ttest hh_member if group<6, by(neg)
ttest hh_member_18 if group<6, by(neg)
ttest risk_averse if group<6, by(neg)
ttest male if group<6, by(neg)
ttest age if group<6, by(neg)
ttest ethnicity if group<6, by(neg)
ttest hh_head if group<6, by(neg)
ttest experience_flood if group<6, by(neg)
ttest flooded if group<6, by(neg)


***Step 1.8: Table A3: Main Results: Details ***
*******************************************************************************
est clear
eststo: svy: qui reg move4 1.info 1.map 1.neg if group < 6
test 1.info + 1.map + 1.neg ==0
eststo: svy: qui reg move4 (1.info 1.map 1.neg)##1.flooded if group < 6
test 1.info + 1.map + 1.neg  + 1.info#1.flooded + 1.map#1.flooded + 1.neg#1.flooded==0
eststo: svy: qui reg move4 1.info 1.map 1.neg experience_flood family_outside c.stuff  c.education c.hh_member c.hh_member_18 c.risk_averse male c.age ethnicity hh_head if group < 6
test 1.info + 1.map + 1.neg ==0
*Jointly significant
eststo: svy: qui reg move4_01 (1.info 1.map 1.neg experience_flood family_outside c.stuff  c.education c.hh_member c.hh_member_18 c.risk_averse male c.age ethnicity hh_head)##1.flooded if group < 6
test 1.info + 1.map + 1.neg  + 1.info#1.flooded + 1.map#1.flooded + 1.neg#1.flooded==0
*Jointly significant

esttab using "Table_A3.csv", replace b(3) se(3) star(* 0.10 ** 0.05 *** 0.01) stats(N r2_a) mtitles("move4>0"  "move4>0 flooded" "move4>0 flooded controls" "move4>0 flooded controls interaction") order(*info* *map* *flooded*)


***Step 1.9: Table A4: Robustness: Alternative Definitions of Willingness to Migrate Variable and of At Risk Dummy ***
*******************************************************************************
est clear
eststo: svy: qui reg move4_01 (1.info 1.map 1.neg experience_flood family_outside c.stuff  c.education c.hh_member c.hh_member_18 c.risk_averse male c.age ethnicity hh_head)##1.flooded if group < 6
eststo: svy: qui reg move4_01 (1.info 1.map 1.neg experience_flood family_outside c.stuff  c.education c.hh_member c.hh_member_18 c.risk_averse male c.age ethnicity hh_head)##1.flooded50 if group < 6
eststo: svy: qui reg move4_01 (1.info 1.map 1.neg experience_flood family_outside c.stuff  c.education c.hh_member c.hh_member_18 c.risk_averse male c.age ethnicity hh_head)##c.PFlood2050 if group < 6
eststo: svy: qui reg move4 (1.info 1.map 1.neg experience_flood family_outside c.stuff  c.education c.hh_member c.hh_member_18 c.risk_averse male c.age ethnicity hh_head)##1.flooded if group < 6
eststo: svy: nbreg move4 (1.info 1.map 1.neg experience_flood family_outside c.stuff  c.education c.hh_member c.hh_member_18 c.risk_averse male c.age ethnicity hh_head)##1.flooded if group < 6

esttab using "Table_A4.csv", replace b(3) se(3) star(* 0.10 ** 0.05 *** 0.01) stats(N r2_a) mtitles("baseline"  "move flooded50" "move PFlooded2050" "move continuous OLS" "move continuous NB") order(*info* *map* *flooded*)

***Step 1.10: Table A5: Robustness: Additional Sensitivity ***
*******************************************************************************
est clear
eststo: svy: qui reg move4_01 (1.info 1.map 1.neg experience_flood family_outside c.stuff  c.education c.hh_member c.hh_member_18 c.risk_averse male c.age ethnicity hh_head)##1.flooded if group < 6
eststo: svy: qui reg move4x01 (1.info 1.map 1.neg experience_flood family_outside c.stuff  c.education c.hh_member c.hh_member_18 c.risk_averse male c.age ethnicity hh_head)##1.flooded 
eststo: svy: qui reg move4x01 (1.info 1.map 1.neg 1.control experience_flood family_outside c.stuff  c.education c.hh_member c.hh_member_18 c.risk_averse male c.age ethnicity hh_head)##1.flooded
eststo: svy: qui prob move4_01 (1.info 1.map 1.neg experience_flood family_outside c.stuff  c.education c.hh_member c.hh_member_18 c.risk_averse male c.age ethnicity hh_head)##1.flooded if group < 6
eststo: svy: qui reg move4_01 (1.info 1.map 1.neg flooded  family_outside c.stuff  c.education c.hh_member c.hh_member_18 c.risk_averse male c.age ethnicity hh_head)##1.experience_flood
eststo: svy: reg move4_01 (i.group experience_flood family_outside c.stuff  c.education c.hh_member c.hh_member_18 c.risk_averse male c.age ethnicity hh_head)##1.flooded if group < 6

esttab using "Table_A5.csv", replace b(3) se(3) star(* 0.10 ** 0.05 *** 0.01) stats(N r2_a) mtitles("baseline" "full sample" "control placebo" "probit" "experience_flood" "Full Treatments") order(*info* *map* *flooded* *control*)

***Step 1.11: Table A6: Mechanisms ***
*******************************************************************************
est clear

eststo: svy: qui reg worried (1.info 1.map 1.neg experience_flood family_outside c.stuff  c.education c.hh_member c.hh_member_18 c.risk_averse male c.age ethnicity hh_head)##1.flooded if group < 6
eststo: svy: qui reg move_env (1.info 1.map 1.neg experience_flood family_outside c.stuff  c.education c.hh_member c.hh_member_18 c.risk_averse male c.age ethnicity hh_head)##1.flooded if group < 6
eststo: svy: qui reg iProtect (1.info 1.map 1.neg experience_flood family_outside c.stuff  c.education c.hh_member c.hh_member_18 c.risk_averse male c.age ethnicity hh_head)##1.flooded if group < 6
eststo: svy: qui reg gProtect (1.info 1.map 1.neg experience_flood family_outside c.stuff  c.education c.hh_member c.hh_member_18 c.risk_averse male c.age ethnicity hh_head)##1.flooded if group < 6

esttab using "Table_A6.csv", replace b(3) se(3) star(* 0.10 ** 0.05 *** 0.01) stats(N r2_a) mtitles("iProtect" "gProtect") order(*info* *map* *flooded*)

*******************************************************************************
*** End of Paper Replication Code ***
*******************************************************************************
